package org.kazao.calendar;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Point;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.util.Calendar;
import java.util.Date;
import java.util.Vector;
import javax.swing.BorderFactory;
import javax.swing.JComboBox;
import javax.swing.JComponent;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JInternalFrame;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.JWindow;

public class KazaoCalendarDateTime extends javax.swing.JPanel {
    private JTextField field = new JTextField();
    private JPanel panel = new JPanel();
    
    private KazaoCalendar calendar;
    
    private JWindow calendarWindow = null;
    
    private Vector items = new Vector();
    
    private int long_month;
    private int short_month;
    
    private boolean loading = false;
    public KazaoCalendarDateTime() {
        initComponents();
        init();
    }
    
    public KazaoCalendarDateTime(KazaoCalendarLocal localize) {
        initComponents();
        init();
        calendar.setLocalize(localize);
        initEditor();
    }
    /**
     * infoFormat is string to infoFormat date
     * d    = date 1 to 31 depending of month
     * dd   = date with leading zero
     * ddd  = short day name
     * dddd = long day name
     * m    = month 1 to 12
     * mm   = month with leading zero
     * mmm  = short month name
     * mmmm = long month name
     * yy   = short year (2 digit)
     * yyyy = long year (4 digit)
     */
    public void setFormat(String format) {
        calendar.getLocalize().setDateTimeFormat(format);
        initEditor();
        updateCalendar();
        setEditable(isEditable());
        setEnabled(isEnabled());
        calendar.showDate();
    }
    
    public String getFormat() {
        return calendar.getLocalize().getDateTimeFormat();
    }
    
    public String getDateTime() {
        return calendar.getDate(getFormat());
    }
    
    public String getDateTime(String format) {
        return calendar.getDate(format);
    }
    
    public void setLocalize(KazaoCalendarLocal localize) {
        calendar.setLocalize(localize);
    }
    
    public KazaoCalendarLocal getLocalize() {
        return calendar.getLocalize();
    }
    
    public void setCalendar(Calendar calendar) {
        this.calendar.setCalendar(calendar);
    }
    
    public void setDateTime(String dateTime, String dateTimeFormat) throws KazaoCalendarDateTimeException {
        calendar.setDateTime(dateTime, dateTimeFormat);
    }
    
    public void setDateTime(String dateTime) throws KazaoCalendarDateTimeException {
        calendar.setDateTime(dateTime);
    }
    
    public void setDate(Date date) {
        calendar.setDate(date);
    }
    
    public void setDate(java.sql.Date date) {
        calendar.setDate(date);
    }
    
    public void setTime(java.sql.Time time) {
        calendar.setDate(time);
    }
    
    public Calendar getCalendar() {
        return calendar.getCalendar();
    }
    
    public void setBackgroundColor(Color background) {
        field.setBackground(background);
        for (int i=0; i < items.size(); i++) {
            Item x = (Item) items.elementAt(i);
            x.component.setBackground(background);
        }
        tSeparator.setBackground(background);
    }
    
    public Color getBackgroundColor() {
        return field.getBackground();
    }
    
    public void setForegroundColor(Color foreground) {
        field.setForeground(foreground);
        for (int i=0; i < items.size(); i++) {
            Item x = (Item) items.elementAt(i);
            x.component.setForeground(foreground);
        }
        tSeparator.setForeground(foreground);
    }
    
    public Color getForegroundColor() {
        return field.getForeground();
    }
    
    public void setEnabled(boolean flag) {
        field.setEnabled(flag);
        for (int i=0; i < items.size(); i++) {
            Item x = (Item) items.elementAt(i);
            x.component.setEnabled(flag);
        }
        tSeparator.setEnabled(flag);
        cButton.setEnabled(flag);
        setBackgroundColor(field.getBackground());
        setForegroundColor(field.getForeground());
    }
    
    public boolean isEnabled() {
        return field.isEnabled();
    }
    
    public void setEditable(boolean flag) {
        field.setEditable(flag);
        for (int i=0; i < items.size(); i++) {
            Item x = (Item) items.elementAt(i);
            if (!x.component.getName().startsWith("sp")) {
                if (x.component.getClass().getSimpleName().equals(JTextField.class.getSimpleName())) {
                    ((JTextField) x.component).setEditable(flag);
                }
                if (x.component.getClass().getSimpleName().equals(JComboBox.class.getSimpleName())) {
                    ((JComboBox) x.component).setEditable(flag);
                }
            }
        }
        setBackgroundColor(field.getBackground());
        setForegroundColor(field.getForeground());
    }
    
    public boolean isEditable() {
        return field.isEditable();
    }
    
    public void setFontDate(Font font) {
        field.setFont(font);
        for (int i=0; i < items.size(); i++) {
            Item x = (Item) items.elementAt(i);
            if (x.component.getClass().getSimpleName().equals(JTextField.class.getSimpleName())) {
                ((JTextField) x.component).setFont(font);
            }
            if (x.component.getClass().getSimpleName().equals(JComboBox.class.getSimpleName())) {
                ((JComboBox) x.component).setFont(font);
            }
        }
    }
    
    public Font getFontDate() {
        return field.getFont();
    }
    
    public void setButtonVisible(boolean flag) {
        cButton.setVisible(flag);
    }
    
    public boolean isButtonVisible() {
        return cButton.isVisible();
    }
    
    public void setKazaoCalendar(KazaoCalendar calendar) {
        this.calendar = calendar;
    }
    
    public KazaoCalendar getKazaoCalendar() {
        return calendar;
    }
    
    public void addChangeListener(KazaoCalendarAdapter adapter) {
        getKazaoCalendar().addChangeListener(adapter);
    }
    
    private void init() {
        calendar = new KazaoCalendar();
        
        calendar.addChangeListener(new KazaoCalendarAdapter() {
            public void onChange(Calendar calendar) {
                updateCalendar();
            }
            public void onChange(KazaoCalendar calendar) {                
            }
            public void onDoubleClick() {
                hideCalendar();
            }
        });
        
        initEditor();
        calendar.today();
    }
    
    private void initEditor() {
        createEditor();
        
        setBackgroundColor(field.getBackground());
        setForegroundColor(field.getForeground());
        setEnabled(true);
        setEditable(true);
        setBorder(field.getBorder());
        pEditor.updateUI();
    }
    
    private void createEditor() {
        items.removeAllElements();
        String f = calendar.getLocalize().getDateTimeFormat();//.toLowerCase();
        long_month = 0;
        for (int i=0; i < getLocalize().getLongMonths().length; i++) {
            if (getLocalize().getLongMonths()[i].length() > long_month) {
                long_month = getLocalize().getLongMonths()[i].length();
            }
        }
        short_month = 0;
        for (int i=0; i < getLocalize().getShortMonths().length; i++) {
            if (getLocalize().getShortMonths()[i].length() > short_month) {
                short_month = getLocalize().getShortMonths()[i].length();
            }
        }
        while (true) {
            int index_d = f.indexOf("d");
            int index_m = f.indexOf("m");
            int index_y = f.indexOf("y");
            int index_h = f.indexOf("h");
            int index_i = f.indexOf("i");
            int index_s = f.indexOf("s");
            if (index_d != -1 &&
                    f.substring(0, index_d).indexOf("m") == -1 &&
                    f.substring(0, index_d).indexOf("y") == -1 &&
                    f.substring(0, index_d).indexOf("h") == -1 &&
                    f.substring(0, index_d).indexOf("i") == -1 &&
                    f.substring(0, index_d).indexOf("s") == -1) {
                if (index_d > 0) {
                    JTextField tf = new JTextField();
                    tf.setName("sp"+items.size());
                    tf.setText(f.substring(0, index_d));
                    items.add(new Item(tf, "sp"));
                    f = f.substring(index_d);
                }
                if (f.startsWith("ddd")) {
                    JComboBox cb = new JComboBox();
                    cb.setName("dd"+items.size());
                    cb.setPreferredSize(new Dimension(24+16, getHeight()));
                    items.add(new Item(cb, "ddd"));
                    f = f.substring(3);
                } else if (f.startsWith("dd")) {
                    JTextField tf = new JTextField();
                    tf.setName("dd"+items.size());
                    tf.setPreferredSize(new Dimension(16, getHeight()));
                    items.add(new Item(tf, "dd"));
                    f = f.substring(2);
                } else {
                    JTextField tf = new JTextField();
                    tf.setName("dd"+items.size());
                    tf.setPreferredSize(new Dimension(16, getHeight()));
                    items.add(new Item(tf, "d"));
                    f = f.substring(1);
                }
            } else if (index_m != -1 &&
                    f.substring(0, index_m).indexOf("d") == -1 &&
                    f.substring(0, index_m).indexOf("y") == -1 &&
                    f.substring(0, index_m).indexOf("h") == -1 &&
                    f.substring(0, index_m).indexOf("i") == -1 &&
                    f.substring(0, index_m).indexOf("s") == -1) {
                if (index_m > 0) {
                    JTextField tf = new JTextField();
                    tf.setName("sp"+items.size());
                    tf.setText(f.substring(0, index_m));
                    tf.setPreferredSize(new Dimension(f.substring(0, index_m).length()*8, getHeight()));
                    items.add(new Item(tf, "sp"));
                    f = f.substring(index_m);
                }
                if (f.startsWith("mmmm")) {
                    JComboBox cb = new JComboBox(getLocalize().getLongMonths());
                    cb.setName("mm"+items.size());
                    cb.setPreferredSize(new Dimension(8*long_month+16, getHeight()));
                    items.add(new Item(cb, "mmmm"));
                    f = f.substring(4);
                } else if (f.startsWith("mmm")) {
                    JTextField tf = new JTextField();
                    tf.setName("mm"+items.size());
                    tf.setPreferredSize(new Dimension(8*short_month, getHeight()));
                    items.add(new Item(tf, "mmm"));
                    f = f.substring(3);
                } else if (f.startsWith("mm")) {
                    JTextField tf = new JTextField();
                    tf.setName("mm"+items.size());
                    tf.setPreferredSize(new Dimension(16, getHeight()));
                    items.add(new Item(tf, "mm"));
                    f = f.substring(2);
                } else {
                    JTextField tf = new JTextField();
                    tf.setName("mm"+items.size());
                    tf.setPreferredSize(new Dimension(16, getHeight()));
                    items.add(new Item(tf, "m"));
                    f = f.substring(1);
                }
            } else if (index_y != -1 &&
                    f.substring(0, index_y).indexOf("d") == -1 &&
                    f.substring(0, index_y).indexOf("m") == -1 &&
                    f.substring(0, index_y).indexOf("h") == -1 &&
                    f.substring(0, index_y).indexOf("i") == -1 &&
                    f.substring(0, index_y).indexOf("s") == -1) {
                if (index_y > 0) {
                    JTextField tf = new JTextField();
                    tf.setName("sp"+items.size());
                    tf.setText(f.substring(0, index_y));
                    items.add(new Item(tf, "sp"));
                    f = f.substring(index_y);
                }
                if (f.startsWith("yyyyy")) {
                    JComboBox cb = new JComboBox();
                    for (int i=getLocalize().getMinYear(); i <= getLocalize().getMaxYear(); i++) {
                        cb.addItem(""+i);
                    }
                    cb.setName("yy"+items.size());
                    cb.setPreferredSize(new Dimension(8*5+16, getHeight()));
                    items.add(new Item(cb, "yyyyy"));
                    f = f.substring(5);
                } else if (f.startsWith("yyyy")) {
                    JTextField tf = new JTextField();
                    tf.setName("yy"+items.size());
                    tf.setPreferredSize(new Dimension(32, getHeight()));
                    items.add(new Item(tf, "yyyy"));
                    f = f.substring(4);
                } else if (f.startsWith("yyy")) {
                    JTextField tf = new JTextField();
                    tf.setName("yy"+items.size());
                    tf.setPreferredSize(new Dimension(32, getHeight()));
                    items.add(new Item(tf, "yyyy"));
                    f = f.substring(3);
                } else if (f.startsWith("yy")) {
                    JTextField tf = new JTextField();
                    tf.setName("yy"+items.size());
                    tf.setPreferredSize(new Dimension(16, getHeight()));
                    items.add(new Item(tf, "yy"));
                    f = f.substring(2);
                } else {
                    JTextField tf = new JTextField();
                    tf.setName("yy"+items.size());
                    tf.setPreferredSize(new Dimension(16, getHeight()));
                    items.add(new Item(tf, "yy"));
                    f = f.substring(1);
                }
            } else if (index_h != -1 &&
                    f.substring(0, index_h).indexOf("d") == -1 &&
                    f.substring(0, index_h).indexOf("m") == -1 &&
                    f.substring(0, index_h).indexOf("y") == -1 &&
                    f.substring(0, index_h).indexOf("i") == -1 &&
                    f.substring(0, index_h).indexOf("s") == -1) {
                if (index_h > 0) {
                    JTextField tf = new JTextField();
                    tf.setName("sp"+items.size());
                    tf.setText(f.substring(0, index_h));
                    items.add(new Item(tf, "sp"));
                    f = f.substring(index_h);
                }
                if (f.startsWith("hhh")) {
                    JComboBox cb = new JComboBox();
                    for (int i=0; i < 24; i++) {
                        cb.addItem(KazaoCalendarUtil.lpad(""+i, 2, "0"));
                    }
                    cb.setName("hh"+items.size());
                    cb.setPreferredSize(new Dimension(24+16, getHeight()));
                    items.add(new Item(cb, "hhh"));
                    f = f.substring(3);
                } else if (f.startsWith("hh")) {
                    JTextField tf = new JTextField();
                    tf.setName("hh"+items.size());
                    tf.setPreferredSize(new Dimension(16, getHeight()));
                    items.add(new Item(tf, "hh"));
                    f = f.substring(2);
                } else {
                    JTextField tf = new JTextField();
                    tf.setName("hh"+items.size());
                    tf.setPreferredSize(new Dimension(16, getHeight()));
                    items.add(new Item(tf, "h"));
                    f = f.substring(1);
                }
            } else if (index_i != -1 &&
                    f.substring(0, index_i).indexOf("d") == -1 &&
                    f.substring(0, index_i).indexOf("m") == -1 &&
                    f.substring(0, index_i).indexOf("y") == -1 &&
                    f.substring(0, index_i).indexOf("h") == -1 &&
                    f.substring(0, index_i).indexOf("s") == -1) {
                if (index_i > 0) {
                    JTextField tf = new JTextField();
                    tf.setName("sp"+items.size());
                    tf.setText(f.substring(0, index_i));
                    items.add(new Item(tf, "sp"));
                    f = f.substring(index_i);
                }
                if (f.startsWith("iii")) {
                    JComboBox cb = new JComboBox();
                    for (int i=0; i < 60; i++) {
                        cb.addItem(KazaoCalendarUtil.lpad(""+i, 2, "0"));
                    }
                    cb.setName("ii"+items.size());
                    cb.setPreferredSize(new Dimension(24+16, getHeight()));
                    items.add(new Item(cb, "iii"));
                    f = f.substring(3);
                } else if (f.startsWith("ii")) {
                    JTextField tf = new JTextField();
                    tf.setName("ii"+items.size());
                    tf.setPreferredSize(new Dimension(16, getHeight()));
                    items.add(new Item(tf, "ii"));
                    f = f.substring(2);
                } else {
                    JTextField tf = new JTextField();
                    tf.setName("ii"+items.size());
                    tf.setPreferredSize(new Dimension(16, getHeight()));
                    items.add(new Item(tf, "i"));
                    f = f.substring(1);
                }
            } else if (index_s != -1 &&
                    f.substring(0, index_s).indexOf("d") == -1 &&
                    f.substring(0, index_s).indexOf("m") == -1 &&
                    f.substring(0, index_s).indexOf("y") == -1 &&
                    f.substring(0, index_s).indexOf("h") == -1 &&
                    f.substring(0, index_s).indexOf("i") == -1) {
                if (index_s > 0) {
                    JTextField tf = new JTextField();
                    tf.setName("sp"+items.size());
                    tf.setText(f.substring(0, index_s));
                    items.add(new Item(tf, "sp"));
                    f = f.substring(index_s);
                }
                if (f.startsWith("sss")) {
                    JComboBox cb = new JComboBox();
                    for (int i=0; i < 60; i++) {
                        cb.addItem(KazaoCalendarUtil.lpad(""+i, 2, "0"));
                    }
                    cb.setName("ss"+items.size());
                    cb.setPreferredSize(new Dimension(24+16, getHeight()));
                    items.add(new Item(cb, "sss"));
                    f = f.substring(3);
                } else if (f.startsWith("ss")) {
                    JTextField tf = new JTextField();
                    tf.setName("ss"+items.size());
                    tf.setPreferredSize(new Dimension(16, getHeight()));
                    items.add(new Item(tf, "ss"));
                    f = f.substring(2);
                } else {
                    JTextField tf = new JTextField();
                    tf.setName("ss"+items.size());
                    tf.setPreferredSize(new Dimension(16, getHeight()));
                    items.add(new Item(tf, "s"));
                    f = f.substring(1);
                }
            } else {
                JTextField tf = new JTextField();
                tf.setName("sp"+items.size());
                tf.setText(f);
                //tf.setPreferredSize(new Dimension(f.length()*8, getHeight()));
                items.add(new Item(tf, "sp"));
                f = "";
            }
            if (f.equals("")) {
                break;
            }
        }
        pEditor.removeAll();
        for (int i=0; i < items.size(); i++) {
            Item x = (Item) items.elementAt(i);
            if (!x.component.getName().startsWith("sp")) {
                if (x.component.getClass().getSimpleName().equals(JTextField.class.getSimpleName())) {
                    setListener((JTextField) x.component);
                    ((JTextField) x.component).setHorizontalAlignment(JTextField.CENTER);
                    ((JTextField) x.component).setBorder(BorderFactory.createEmptyBorder());
                }
                if (x.component.getClass().getSimpleName().equals(JComboBox.class.getSimpleName())) {
                    setListener((JComboBox) x.component);
                    JComboBox cb = (JComboBox) x.component;
                    cb.setFont(new Font(cb.getFont().getName(), Font.PLAIN, cb.getFont().getSize()));
                    cb.setBorder(BorderFactory.createEmptyBorder());
                }
            } else {
                ((JTextField) x.component).setEditable(false);
                ((JTextField) x.component).setBorder(BorderFactory.createEmptyBorder());
            }
            pEditor.add(x.component);
        }
    }
    
    private void updateCalendar() {
        for (int i=0; i < items.size(); i++) {
            Item x = (Item) items.elementAt(i);
            if (!x.component.getName().startsWith("sp")) {
                if (x.component.getClass().getSimpleName().equals(JTextField.class.getSimpleName())) {
                    JTextField tf = (JTextField) x.component;
                    if (x.format.equals("d")) {
                        tf.setText(""+calendar.getCalendar().get(Calendar.DATE));
                    } else if (x.format.equals("dd")) {
                        tf.setText(KazaoCalendarUtil.lpad(""+calendar.getCalendar().get(Calendar.DATE), 2, "0"));
                    } else if (x.format.equals("m")) {
                        tf.setText(""+(calendar.getCalendar().get(Calendar.MONTH)+1));
                    } else if (x.format.equals("mm")) {
                        tf.setText(KazaoCalendarUtil.lpad(""+(calendar.getCalendar().get(Calendar.MONTH)+1), 2, "0"));
                    } else if (x.format.equals("mmm")) {
                        tf.setText(getLocalize().getShortMonths()[calendar.getCalendar().get(Calendar.MONTH)]);
                    } else if (x.format.equals("yy")) {
                        tf.setText(new String(""+calendar.getCalendar().get(Calendar.YEAR)).substring(2, 4));
                    } else if (x.format.equals("yyyy")) {
                        tf.setText(KazaoCalendarUtil.lpad(""+calendar.getCalendar().get(Calendar.YEAR), 4, "0"));
                    } else if (x.format.equals("h")) {
                        tf.setText(""+calendar.getCalendar().get(Calendar.HOUR_OF_DAY));
                    } else if (x.format.equals("hh")) {
                        tf.setText(KazaoCalendarUtil.lpad(""+calendar.getCalendar().get(Calendar.HOUR_OF_DAY), 2, "0"));
                    } else if (x.format.equals("i")) {
                        tf.setText(""+calendar.getCalendar().get(Calendar.MINUTE));
                    } else if (x.format.equals("ii")) {
                        tf.setText(KazaoCalendarUtil.lpad(""+calendar.getCalendar().get(Calendar.MINUTE), 2, "0"));
                    } else if (x.format.equals("s")) {
                        tf.setText(""+calendar.getCalendar().get(Calendar.SECOND));
                    } else if (x.format.equals("ss")) {
                        tf.setText(KazaoCalendarUtil.lpad(""+calendar.getCalendar().get(Calendar.SECOND), 2, "0"));
                    }
                }
                if (x.component.getClass().getSimpleName().equals(JComboBox.class.getSimpleName())) {
                    JComboBox cb = (JComboBox) x.component;
                    if (x.format.equals("ddd")) {
                        loading = true;
                        cb.removeAllItems();
                        for (int t=1; t <= calendar.getMaxDay(getCalendar()); t++) {
                            cb.addItem(""+t);
                        }
                        loading = false;
                        cb.setSelectedIndex(calendar.getCalendar().get(Calendar.DATE)-1);
                    } else if (x.format.equals("mmmm")) {
                        cb.setSelectedIndex(calendar.getCalendar().get(Calendar.MONTH));
                    } else if (x.format.equals("yyyyy")) {
                        cb.setSelectedIndex(calendar.getCalendar().get(Calendar.YEAR)-getLocalize().getMinYear());
                    } else if (x.format.equals("hhh")) {
                        cb.setSelectedIndex(calendar.getCalendar().get(Calendar.HOUR_OF_DAY));
                    } else if (x.format.equals("iii")) {
                        cb.setSelectedIndex(calendar.getCalendar().get(Calendar.MINUTE));
                    } else if (x.format.equals("sss")) {
                        cb.setSelectedIndex(calendar.getCalendar().get(Calendar.SECOND));
                    }
                }
            }
        }
    }
    
    private String getNumber(String text) {
        char[] a = new char[] {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9'};
        StringBuffer buffer = new StringBuffer("");
        for (int i=0; i < text.length(); i++) {
            if (KazaoCalendarUtil.inArray(a, text.charAt(i))) {
                buffer.append(text.charAt(i));
            } else {
                break;
            }
        }
        if (buffer.toString().equals("")) {
            buffer = new StringBuffer("-1");
        }
        return buffer.toString();
    }
    
    private void setListener(JTextField tf) {
        tf.addKeyListener(new java.awt.event.KeyAdapter() {
            public void keyTyped(java.awt.event.KeyEvent evt) {
                char[] a = new char[] {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9'};
                Item x = (Item) items.elementAt(getEditorIndex((JComponent) evt.getSource()));
                JTextField tf = (JTextField) x.component;
                String text = tf.getText()+evt.getKeyChar();
                text = getNumber(text);
                if (x.format.equals("d") || x.format.equals("dd")) {
                    if (!KazaoCalendarUtil.inArray(a, evt.getKeyChar()) || tf.getText().length() == 2) {
                        evt.setKeyChar((char) 0);
                    } else {
                        if (Integer.parseInt(text) < 1 || Integer.parseInt(text) > calendar.getMaxDay(getCalendar())) {
                            evt.setKeyChar((char) 0);
                        }
                    }
                }
                if (x.format.equals("m") || x.format.equals("mm")) {
                    if (!KazaoCalendarUtil.inArray(a, evt.getKeyChar()) || tf.getText().length() == 2) {
                        evt.setKeyChar((char) 0);
                    } else {
                        if (!text.equals("")) {
                            if (Integer.parseInt(text) > 12) {
                                evt.setKeyChar((char) 0);
                            }
                        }
                    }
                }
                if (x.format.equals("mmm")) {
                    if (tf.getText().length() == short_month) {
                        evt.setKeyChar((char) 0);
                    }
                }
                if (x.format.equals("yy")) {
                    if (!KazaoCalendarUtil.inArray(a, evt.getKeyChar()) || tf.getText().length() == 2) {
                        evt.setKeyChar((char) 0);
                    } else {
                        if (!text.equals("")) {
                            if (Integer.parseInt(text) < 0) {
                                evt.setKeyChar((char) 0);
                            }
                        }
                    }
                }
                if (x.format.equals("yyyy")) {
                    if (!KazaoCalendarUtil.inArray(a, evt.getKeyChar()) || tf.getText().length() == 4) {
                        evt.setKeyChar((char) 0);
                    } else {
                        if (!text.equals("")) {
                            if (Integer.parseInt(text) > getLocalize().getMaxYear()) {
                                evt.setKeyChar((char) 0);
                            }
                        }
                    }
                }
                if (x.format.equals("h") || x.format.equals("hh")) {
                    if (!KazaoCalendarUtil.inArray(a, evt.getKeyChar()) || tf.getText().length() == 2) {
                        evt.setKeyChar((char) 0);
                    } else {
                        if (!text.equals("")) {
                            if (Integer.parseInt(text) >= 24) {
                                evt.setKeyChar((char) 0);
                            }
                        }
                    }
                }
                if (x.format.equals("i") || x.format.equals("ii")) {
                    if (!KazaoCalendarUtil.inArray(a, evt.getKeyChar()) || tf.getText().length() == 2) {
                        evt.setKeyChar((char) 0);
                    } else {
                        if (!text.equals("")) {
                            if (Integer.parseInt(text) >= 60) {
                                evt.setKeyChar((char) 0);
                            }
                        }
                    }
                }
                if (x.format.equals("s") || x.format.equals("ss")) {
                    if (!KazaoCalendarUtil.inArray(a, evt.getKeyChar()) || tf.getText().length() == 2) {
                        evt.setKeyChar((char) 0);
                    } else {
                        if (!text.equals("")) {
                            if (Integer.parseInt(text) >= 60) {
                                evt.setKeyChar((char) 0);
                            }
                        }
                    }
                }
            }
            public void keyPressed(java.awt.event.KeyEvent evt) {
                if (evt.getKeyCode() == evt.VK_LEFT) {
                    focusPrev(getEditorIndex((JComponent) evt.getSource()));
                }
                if (evt.getKeyCode() == evt.VK_RIGHT) {
                    focusNext(getEditorIndex((JComponent) evt.getSource()));
                }
                if (evt.getKeyCode() == evt.VK_UP) {
                    Item x = (Item) items.elementAt(getEditorIndex((JComponent) evt.getSource()));
                    if (x.format.equals("d") || x.format.equals("dd")) {
                        if (!calendar.isMax()) {
                            calendar.getCalendar().add(Calendar.DATE, 1);
                            calendar.update();
                        }
                    }
                    if (x.format.equals("m") || x.format.equals("mm") || x.format.equals("mmm")) {
                        if (!calendar.isMax('m')) {
                            calendar.getCalendar().add(Calendar.MONTH, 1);
                            calendar.update();
                        }
                    }
                    if (x.format.equals("yy") || x.format.equals("yyyy")) {
                        if (getCalendar().get(Calendar.YEAR) < getLocalize().getMaxYear()) {
                            getCalendar().add(Calendar.YEAR, 1);
                            calendar.update();
                        }
                    }
                    if (x.format.equals("h") || x.format.equals("hh")) {
                        if (!calendar.isMax('h')) {
                            calendar.getCalendar().add(Calendar.HOUR_OF_DAY, 1);
                            calendar.update();
                        }
                    }
                    if (x.format.equals("i") || x.format.equals("ii")) {
                        if (!calendar.isMax('i')) {
                            calendar.getCalendar().add(Calendar.MINUTE, 1);
                            calendar.update();
                        }
                    }
                    if (x.format.equals("s") || x.format.equals("ss")) {
                        if (!calendar.isMax('s')) {
                            calendar.getCalendar().add(Calendar.SECOND, 1);
                            calendar.update();
                        }
                    }
                }
                if (evt.getKeyCode() == evt.VK_DOWN) {
                    Item x = (Item) items.elementAt(getEditorIndex((JComponent) evt.getSource()));
                    if (x.format.equals("d") || x.format.equals("dd")) {
                        if (!calendar.isMin()) {
                            calendar.getCalendar().add(Calendar.DATE, -1);
                            calendar.update();
                        }
                    }
                    if (x.format.equals("m") || x.format.equals("mm") || x.format.equals("mmm")) {
                        if (!calendar.isMin('m')) {
                            calendar.getCalendar().add(Calendar.MONTH, -1);
                            calendar.update();
                        }
                    }
                    if (x.format.equals("yy") || x.format.equals("yyyy")) {
                        if (getCalendar().get(Calendar.YEAR) > getLocalize().getMinYear()) {
                            getCalendar().add(Calendar.YEAR, -1);
                            calendar.update();
                        }
                    }
                    if (x.format.equals("h") || x.format.equals("hh")) {
                        if (!calendar.isMin('h')) {
                            calendar.getCalendar().add(Calendar.HOUR_OF_DAY, -1);
                            calendar.update();
                        }
                    }
                    if (x.format.equals("i") || x.format.equals("ii")) {
                        if (!calendar.isMin('i')) {
                            calendar.getCalendar().add(Calendar.MINUTE, -1);
                            calendar.update();
                        }
                    }if (x.format.equals("s") || x.format.equals("ss")) {
                        if (!calendar.isMin('s')) {
                            calendar.getCalendar().add(Calendar.SECOND, -1);
                            calendar.update();
                        }
                    }
                    
                }
                if (evt.getKeyCode() == evt.VK_PAGE_UP) {
                    Item x = (Item) items.elementAt(getEditorIndex((JComponent) evt.getSource()));
                    if (x.format.equals("d") || x.format.equals("dd")) {
                        calendar.getCalendar().set(Calendar.DATE, calendar.getMaxDay(getCalendar()));
                        calendar.update();
                    }
                    if (x.format.equals("m") || x.format.equals("mm") || x.format.equals("mmm")) {
                        calendar.getCalendar().set(Calendar.MONTH, 11);
                        calendar.update();
                    }
                    if (x.format.equals("yy") || x.format.equals("yyyy")) {
                        calendar.getCalendar().set(Calendar.YEAR, getLocalize().getMaxYear());
                        calendar.update();
                    }
                    if (x.format.equals("h") || x.format.equals("hh")) {
                        calendar.getCalendar().set(Calendar.HOUR_OF_DAY, 23);
                        calendar.update();
                    }
                    if (x.format.equals("i") || x.format.equals("ii")) {
                        calendar.getCalendar().set(Calendar.MINUTE, 59);
                        calendar.update();
                    }
                    if (x.format.equals("s") || x.format.equals("ss")) {
                        calendar.getCalendar().set(Calendar.SECOND, 59);
                        calendar.update();
                    }
                }
                if (evt.getKeyCode() == evt.VK_PAGE_DOWN) {
                    Item x = (Item) items.elementAt(getEditorIndex((JComponent) evt.getSource()));
                    if (x.format.equals("d") || x.format.equals("dd")) {
                        calendar.getCalendar().set(Calendar.DATE, 1);
                        calendar.update();
                    }
                    if (x.format.equals("m") || x.format.equals("mm") || x.format.equals("mmm")) {
                        calendar.getCalendar().set(Calendar.MONTH, 0);
                        calendar.update();
                    }
                    if (x.format.equals("yy") || x.format.equals("yyyy")) {
                        calendar.getCalendar().set(Calendar.YEAR, getLocalize().getMinYear());
                        calendar.update();
                    }
                    if (x.format.equals("hh") || x.format.equals("hh")) {
                        calendar.getCalendar().set(Calendar.HOUR_OF_DAY, 0);
                        calendar.update();
                    }
                    if (x.format.equals("i") || x.format.equals("ii")) {
                        calendar.getCalendar().set(Calendar.MINUTE, 0);
                        calendar.update();
                    }
                    if (x.format.equals("s") || x.format.equals("ss")) {
                        calendar.getCalendar().set(Calendar.SECOND, 0);
                        calendar.update();
                    }
                }
                if (evt.getKeyCode() == evt.VK_ENTER) {
                    saveEdit((JComponent) evt.getSource());
                    calendar.update();
                }
            }
        });
        tf.addFocusListener(new java.awt.event.FocusAdapter() {
            public void focusLost(java.awt.event.FocusEvent evt) {
                saveEdit((JComponent) evt.getSource());
                calendar.update();
            }
        });
    }
    
    private void saveEdit(JComponent component) {
        Item x = (Item) items.elementAt(getEditorIndex(component));
        if (x.format.equals("mmm")) {
            int a = -1;
            for (int i=0; i < getLocalize().getShortMonths().length; i++) {
                if (((JTextField) x.component).getText().toLowerCase().equals(getLocalize().getShortMonths()[i].toLowerCase())) {
                    a = i;
                    break;
                }
            }
            if (a != -1) {
                calendar.getCalendar().set(Calendar.MONTH, a);
            }
        } else {
            int value = Integer.parseInt(getNumber(((JTextField) x.component).getText()));
            if (x.format.equals("d") || x.format.equals("dd")) {
                if (value >= 1 && value <= calendar.getMaxDay(getCalendar())) {
                    calendar.getCalendar().set(Calendar.DATE, value);
                }
            }
            if (x.format.equals("m") || x.format.equals("mm")) {
                if (value > 0 && value <= 12) {
                    calendar.getCalendar().set(Calendar.MONTH, value-1);
                }
            }
            if (x.format.equals("yyyy")) {
                if (value >= getLocalize().getMinYear() && value <= getLocalize().getMaxYear()) {
                    getCalendar().set(Calendar.YEAR, value);
                }
            }
            if (x.format.equals("yy")) {
                String s = new String(""+getCalendar().get(Calendar.YEAR)).substring(0, 2)+((JTextField) x.component).getText();
                value = Integer.parseInt(s);
                if (value >= getLocalize().getMinYear() && value <= getLocalize().getMaxYear()) {
                    getCalendar().set(Calendar.YEAR, value);
                }
            }
            if (x.format.equals("h") || x.format.equals("hh")) {
                if (value > 0 && value <= 23) {
                    calendar.getCalendar().set(Calendar.HOUR_OF_DAY, value);
                }
            }
            if (x.format.equals("i") || x.format.equals("ii")) {
                if (value > 0 && value <= 59) {
                    calendar.getCalendar().set(Calendar.MINUTE, value);
                }
            }
            if (x.format.equals("s") || x.format.equals("ss")) {
                if (value > 0 && value <= 59) {
                    calendar.getCalendar().set(Calendar.SECOND, value);
                }
            }
        }
    }
    
    
    
    private void focusPrev(int index) {
        for (int i=index-1; i >= 0; i--) {
            Item x = (Item) items.elementAt(i);
            if (!x.component.getName().startsWith("sp")) {
                x.component.requestFocus();
                break;
            }
        }
    }
    
    private void focusNext(int index) {
        for (int i=index+1; i < items.size(); i++) {
            Item x = (Item) items.elementAt(i);
            if (!x.component.getName().startsWith("sp")) {
                x.component.requestFocus();
                break;
            }
        }
    }
    
    private int getEditorIndex(JComponent component) {
        int result = -1;
        for (int i=0; i < items.size(); i++) {
            Item x = (Item) items.elementAt(i);
            if (x.component.equals(component)) {
                result = i;
                break;
            }
        }
        return result;
    }
    
    private void setListener(JComboBox cb) {
        cb.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                Item x = (Item) items.elementAt(getEditorIndex((JComponent) evt.getSource()));
                JComboBox cb = (JComboBox) x.component;
                if (x.format.equals("ddd")) {
                    if (!loading) {
                        calendar.getCalendar().set(Calendar.DATE, cb.getSelectedIndex()+1);
                    }
                } else if (x.format.equals("mmmm")) {
                    calendar.getCalendar().set(Calendar.MONTH, cb.getSelectedIndex());
                } else if (x.format.equals("yyyyy")) {
                    calendar.getCalendar().set(Calendar.YEAR, cb.getSelectedIndex()+getLocalize().getMinYear());
                } else if (x.format.equals("hhh")) {
                    calendar.getCalendar().set(Calendar.HOUR_OF_DAY, cb.getSelectedIndex());
                } else if (x.format.equals("iii")) {
                    calendar.getCalendar().set(Calendar.MINUTE, cb.getSelectedIndex());
                } else if (x.format.equals("sss")) {
                    calendar.getCalendar().set(Calendar.SECOND, cb.getSelectedIndex());
                }
                calendar.update();
            }
        });
    }
    
    private void showCalendar() {
        if (calendarWindow == null) {
            createWindow();
        }
        Point location = getLocationOnScreen();
        Dimension screenSize = getToolkit().getDefaultToolkit().getScreenSize();
        int x = location.x;
        int y = location.y;
        if (screenSize.width-location.x >= calendarWindow.getWidth()) {
            x = location.x;
        } else {
            x = location.x - calendarWindow.getWidth() + getWidth();
        }
        if (x < 0) {
            x = 0;
        }
        if (x + calendarWindow.getWidth() > screenSize.width) {
            x = screenSize.width - calendarWindow.getWidth();
        }
        if (screenSize.height-location.y-getHeight() >= calendarWindow.getHeight()) {
            y = location.y + getHeight();
        } else {
            y = location.y - calendarWindow.getHeight();
        }
        calendarWindow.setBounds(x, y, calendarWindow.getWidth(), calendarWindow.getHeight());
        calendarWindow.setVisible(true);
        calendarWindow.requestFocusInWindow();
    }
    
    private void hideCalendar() {
        calendar.update();
        calendarWindow.setVisible(false);
    }
    private void createWindow() {
        if (getTopLevelAncestor() instanceof JFrame) {
            calendarWindow = new JWindow((JFrame) getTopLevelAncestor(), getGraphicsConfiguration());
        } else if (getTopLevelAncestor() instanceof JDialog) {
            calendarWindow = new JWindow((JDialog) getTopLevelAncestor(), getGraphicsConfiguration());
        } else {
            calendarWindow = new JWindow(getGraphicsConfiguration());
        }
        JInternalFrame iframe = null;
        Component c = this;
        while (true) {
            if (c.getParent() instanceof JInternalFrame) {
                iframe = (JInternalFrame) c.getParent();
                break;
            }
            if (c.getParent().equals(getTopLevelAncestor())) {
                break;
            }
            c = c.getParent();
        }
        if (iframe != null) {
            iframe.addComponentListener(new java.awt.event.ComponentAdapter() {
                public void componentMoved(java.awt.event.ComponentEvent evt) {
                    hideCalendar();
                }
            });
        }
        calendarWindow.getContentPane().setLayout(new BorderLayout());
        calendarWindow.getContentPane().add(calendar, BorderLayout.CENTER);
        calendarWindow.pack();
        calendarWindow.addWindowListener(new WindowAdapter() {
            public void windowDeactivated(WindowEvent e) {
                hideCalendar();
            }
        });
        getTopLevelAncestor().addFocusListener(new java.awt.event.FocusAdapter() {
            public void focusLost(java.awt.event.FocusEvent evt) {
                hideCalendar();
            }
        });
        getTopLevelAncestor().addComponentListener(new ComponentAdapter() {
            public void componentResized(ComponentEvent e) {
                hideCalendar();
            }
            public void componentMoved(ComponentEvent e) {
                hideCalendar();
            }
            public void componentShown(ComponentEvent e) {
                hideCalendar();
            }
            public void componentHidden(ComponentEvent e) {
                hideCalendar();
            }
        });
        parseContainer(getTopLevelAncestor());
    }
    
    private void parseContainer(Container container) {
        container.addMouseListener(new MouseAdapter() {
            public void mouseClicked(MouseEvent e) {
                hideCalendar();
            }
        });
        container.addFocusListener(new java.awt.event.FocusAdapter() {
            public void focusGained(java.awt.event.FocusEvent evt) {
                hideCalendar();
            }
        });
        for (int i=0; i < container.getComponentCount(); i++) {
            if (!container.getComponent(i).equals(this)) {
                if (container.getComponent(i) instanceof JComponent) {
                    ((JComponent) container.getComponent(i)).addMouseListener(new MouseAdapter() {
                        public void mouseClicked(MouseEvent e) {
                            hideCalendar();
                        }
                    });
                    ((JComponent) container.getComponent(i)).addFocusListener(new java.awt.event.FocusAdapter() {
                        public void focusGained(java.awt.event.FocusEvent evt) {
                            hideCalendar();
                        }
                    });
                }
                if (container.getComponent(i) instanceof Container) {
                    parseContainer((Container) container.getComponent(i));
                }
            }
        }
    }
    // <editor-fold defaultstate="collapsed" desc=" Generated Code ">//GEN-BEGIN:initComponents
    private void initComponents() {
        pEditor = new javax.swing.JPanel();
        tSeparator = new javax.swing.JTextField();
        cButton = new javax.swing.JButton();

        setLayout(new java.awt.BorderLayout());

        setBorder(javax.swing.BorderFactory.createEtchedBorder());
        setMinimumSize(new java.awt.Dimension(8060, 16));
        addComponentListener(new java.awt.event.ComponentAdapter() {
            public void componentResized(java.awt.event.ComponentEvent evt) {
                formComponentResized(evt);
            }
        });

        pEditor.setLayout(new javax.swing.BoxLayout(pEditor, javax.swing.BoxLayout.X_AXIS));

        add(pEditor, java.awt.BorderLayout.WEST);

        tSeparator.setEditable(false);
        tSeparator.setBorder(null);
        tSeparator.addFocusListener(new java.awt.event.FocusAdapter() {
            public void focusLost(java.awt.event.FocusEvent evt) {
                tSeparatorFocusLost(evt);
            }
        });

        add(tSeparator, java.awt.BorderLayout.CENTER);

        cButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/kazao/calendar/images/pick.png")));
        cButton.setMnemonic('p');
        cButton.setBorderPainted(false);
        cButton.setFocusPainted(false);
        cButton.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
        cButton.setPreferredSize(new java.awt.Dimension(16, 9));
        cButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                cButtonActionPerformed(evt);
            }
        });

        add(cButton, java.awt.BorderLayout.EAST);

    }// </editor-fold>//GEN-END:initComponents
    
    private void tSeparatorFocusLost(java.awt.event.FocusEvent evt) {//GEN-FIRST:event_tSeparatorFocusLost
// TODO add your handling code here:
    }//GEN-LAST:event_tSeparatorFocusLost
    
    private void formComponentResized(java.awt.event.ComponentEvent evt) {//GEN-FIRST:event_formComponentResized
        cButton.setPreferredSize(new Dimension(getHeight(), getHeight()));
    }//GEN-LAST:event_formComponentResized
    
    private void cButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_cButtonActionPerformed
        if (calendarWindow == null) {
            showCalendar();
        } else {
            if (!calendarWindow.isShowing()) {
                showCalendar();
            } else {
                hideCalendar();
            }
        }
    }//GEN-LAST:event_cButtonActionPerformed
    
    
    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JButton cButton;
    private javax.swing.JPanel pEditor;
    public javax.swing.JTextField tSeparator;
    // End of variables declaration//GEN-END:variables
    
    class Item {
        JComponent component;
        String format;
        Item(JComponent component, String format) {
            this.component = component;
            this.format = format;
        }
    };
}
